/*********************************************************************
	\file :           os_sw_layers\bios\services\osek\Os_TaskM.c
	\brief:           Provide Task Manager services.
	\author:          Manuel Sandoval
	\version:         1.0
	\date:            Sat, 01, March 2014
*********************************************************************/


/******************************* Includes**********************************/

#include "Os_TaskM.h"
#include "SchM.h"
#include "Os_Isr.h"
#include "Fifo_queue.h"


/******************************* Defines **********************************/
/*!< Macros for PORT A */
#define LED_Port    	PORTA
#define D0         		1
#define D1         		2
#define D2         		4
#define D3         		8
#define D4         		16
#define D5         		32
#define D6         		64
#define D7         		128


/*!< Enable LED ON*/
#define LED_ON(BitMask)                     (LED_Port |= (u8)(BitMask))
/*!< Disable LED OFF*/
#define LED_OFF(BitMask)                    (LED_Port &= ~(u8)(BitMask))
/*!< Toggle LED */
#define LED_TOGGLE(BitMask)                 (LED_Port ^= (u8)(BitMask)) 


#define DELAY    1000  

/******************************* Enumerations******************************/


/******************************* Structures *******************************/

/******************************* Prototypes ********************************/

void vfnAttendInterrupt(void);

/******************************* Global Variables **********************************/

extern queue Os_Task_Fifo;
extern Os_TaskControlBlockType Os_Task_ID_Active;
extern boolean Os_Task_Event;

static u8 u8DisableAllIntcnt = 0;
volatile u8 u8Temp_PPage = 0;
volatile u16 u16Temp_PC = 0;
volatile u8 u8Temp_l_A = 0;
Os_TaskStack stOs_MainStack;
Os_TaskStack stOs_TasksStack[TASK_MAX_NUM + 1];
void(*ptr_funcAttendInterrupt)(void) = vfnAttendInterrupt;


/******************************* Functions ********************************/

/***************************************************************************
*
*   FUNCTION NAME: ActivateTask
*
***************************************************************************/
/**
* @brief Provides a single interface to Activate a specific task.
*
*
* @param[in] TaskType - See TaskType.
* @param[in] StatusType - .
*
* @return void.
*
* None.
*
***************************************************************************/

Os_StatusType ActivateTask (TaskType taskID)
{

	if(taskID >= TASK_MAX_NUM)
	{
		/* Input taskID is not a valid task. */
	    return E_OS_ID;
	}
	else
	{
	    /* Indicate that this Task has gained CPU allocation */
	    Os_Task_ID_Active.TaskId = taskID;
	    Os_Task_ID_Active.TaskState = READY;
	}

	/* flag for New task added or finished */
	Os_Task_Event = false;
  
  return E_OK;

} /* ActivateTask */


/***************************************************************************
*
*   FUNCTION NAME: TerminateTask
*
***************************************************************************/
/**
* @brief Provides a single interface to terminate a specific task.
*
*
* @param[in] none.
* @param[out] none.
*
* @return StatusType.
*
* None.
*
***************************************************************************/

Os_StatusType TerminateTask (void)
{
	Os_Task_ID_Active.TaskState = SUSPENDED;

	/* flag for New task added or finished */
	Os_Task_Event = true;

  return E_OK;
} /* TerminateTask */


/***************************************************************************
*
*   FUNCTION NAME: GetTaskID
*
***************************************************************************/
/**
* @brief Provides a single interface to get the Task ID from a specific task.
*
*
* @param[in] TaskRefType.
* @param[out] none.
*
* @return StatusType.
*
* None.
*
***************************************************************************/

/*!< GetTaskID Prototype. */
Os_StatusType GetTaskID(TaskRefType taskIDRef)
{
	if(Os_Task_ID_Active.TaskState == RUNNING)
	{
		taskIDRef = (TaskRefType)&Os_Task_ID_Active.TaskId;
	}
	else
	{
		taskIDRef = (TaskRefType)CNF_INVALID_TASK;
	}

	return E_OK;
} /* GetTaskID */


/***************************************************************************
*
*   FUNCTION NAME: GetTaskState
*
***************************************************************************/
/**
* @brief Provides a single interface to get the Task state from a specific task.
*
*
* @param[in] TaskType.
* @param[in] TaskStateRefType.
*
* @return StatusType.
*
* None.
*
***************************************************************************/

Os_StatusType GetTaskState(TaskType taskID, TaskStateRefType stateRef)
{
	u8 u8Index;
	Os_TaskControlBlockType Os_Task_temp;
	Os_StatusType status = E_OK;

	if(taskID >= TASK_MAX_NUM)
	{
		/* Input taskID is not a valid task. */
	    status = E_OS_ID;
	}
	else
	{
    /* Critical section, do not allow further tasks to enter queue, momentarily */
    //INTERRUPT_DISABLE();

    for(u8Index = 0; u8Index < TASK_MAX_NUM ; u8Index++ )
    {
      if (dequeue(&Os_Task_Fifo, &Os_Task_temp))
      {
        if (Os_Task_temp.TaskId == taskID)
        {
        	stateRef = &Os_Task_temp.TaskState;
        }
        else
        {
        	/* do nothing */
        }

        enqueue(&Os_Task_Fifo, &Os_Task_temp);
      }
      else
      {
        /* do nothing */
      }
    }

    /*End of critical section */
    //INTERRUPT_ENABLE();
	}


    return status;

} /* GetTaskState */


/***************************************************************************
*
*   FUNCTION NAME: vfnSaveTaskContext
*
***************************************************************************/
/**
* @brief Provides a single interface to save the context from a specific task.
*
*
* @param[in] none.
* @param[in] none.
*
* @return void.
*
* None.
*
***************************************************************************/
void vfnSaveTaskContext(Os_TaskStack *stDestiny)
{ 
  (void) stDestiny;
  _asm 
  {
    PULA
    STAA u8Temp_PPage
    PULD 
    STD u16Temp_PC
  }
    
  _asm 
  {
     PULD      
     STD stOs_MainStack.l_CCR 
     PULA      
     STAA stOs_MainStack.l_B  
     PULA      
     STAA stOs_MainStack.l_A  
     PULD      
     STD stOs_MainStack.l_X   
     PULD      
     STD stOs_MainStack.l_Y   
     PULD      
     STD stOs_MainStack.l_PC  
     PULA      
     STAA stOs_MainStack.l_PPage 
     MOVW stOs_MainStack.Callback, 2, -sp 
   }
    
   _asm 
   {
     LDD u16Temp_PC
     PSHD
     LDAA u8Temp_PPage
     PSHA 
     RTC
   } 
}



/***************************************************************************
*
*   FUNCTION NAME: vfnRestoreTaskContext
*
***************************************************************************/
/**
* @brief Provides a single interface to restor the context from a specific task.
*
*
* @param[in] none.
* @param[in] none.
*
* @return void.
*
* None.
*
***************************************************************************/
void vfnRestoreTaskContext(void)
{  
  _asm 
  {
    PULA
    PULD
    PULD
    PULD
    PULD
    PULD
    PULD
  }
    
  _asm 
  {
     LDAA stOs_MainStack.l_PPage
     PSHA
     LDD stOs_MainStack.l_PC
     PSHD
     LDD stOs_MainStack.l_Y
     PSHD
     LDD stOs_MainStack.l_X
     PSHD
     LDAA stOs_MainStack.l_A
     PSHA
     LDAA stOs_MainStack.l_B
     PSHA
     LDD stOs_MainStack.l_CCR
     PSHD
     RTI
  }
}


/***************************************************************************
*
*   FUNCTION NAME: vfnAttendInterrupt
*
***************************************************************************/
/**
* @brief Provides a single interface to attend the interrupts.
*
*
* @param[in] none.
* @param[in] none.
*
* @return void.
*
* None.
*
***************************************************************************/
void vfnAttendInterrupt(void)
{
  TaskType tCurrentRunningTask = INVALID_TASK;
  
  stOs_MainStack.bolstackstored = true;
  
  if(E_OK == GetTaskID (&tCurrentRunningTask))
  {
    stOs_TasksStack[tCurrentRunningTask] = stOs_MainStack;   
  } 
  else
  {
    stOs_TasksStack[TASK_MAX_NUM] = stOs_MainStack;
  }
  
  SchM_Dispatcher();
  
}


/***************************************************************************
*
*   FUNCTION NAME: vfnRunISRRoutine
*
***************************************************************************/
/**
* @brief Provides a single interface to run an interrupt routine.
*
*
* @param[in] none.
* @param[in] none.
*
* @return void.
*
* None.
*
***************************************************************************/
void vfnRunISRRoutine(void)
{
  _asm 
  {
    PULA
    PULD
  }
  
  _asm
  {
    LDD ptr_funcAttendInterrupt
    PSHD
    RTS  
  }
 
}


/***************************************************************************
*
*   FUNCTION NAME: vfnEnableAllInterrupts
*
***************************************************************************/
/**
* @brief Provides a single interface to enable the interrupts.
*
*
* @param[in] none.
* @param[in] none.
*
* @return void.
*
* None.
*
***************************************************************************/
void vfnEnableAllInterrupts(void)
{
	u8DisableAllIntcnt--;          
	if(u8DisableAllIntcnt <= 0)  
	{                                        
		u8DisableAllIntcnt = (0);    
		  {__asm CLI;};                        
	}                                        
}

/***************************************************************************
*
*   FUNCTION NAME: vnfDisableAllInterrupts
*
***************************************************************************/
/**
* @brief Provides a single interface to disble the interrupts.
*
*
* @param[in] none.
* @param[in] none.
*
* @return void.
*
* None.
*
***************************************************************************/
void vnfDisableAllInterrupts(void)
{
  u8DisableAllIntcnt++;
	{__asm SEI;};                            
}



/** @} *//* End of Scheduler Tasks Group */


/*********************************************************************
	File	: os_sw_layers\bios\services\scheduler\SchM_Tasks.c
*********************************************************************/
